﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using StockExchanger.Controllers;
using System.Web.Mvc;
using StockExchanger.Models;
//using StockExchanger.Tests.Fakes;
using Moq;
using StockExchanger.Helpers;
using System.Web.Routing;

namespace StockExchanger.Tests.Controllers {
 /*
    [TestClass]
    public class DsesControllerTest {

        DsesController CreateDsesController() {
            var testData = FakeDseData.CreateTestDses();
            var repository = new FakeDseRepository(testData);

            return new DsesController(repository);
        }

        DsesController CreateDsesControllerAs(string userName) {

            var mock = new Mock<ControllerContext>();
            mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
            mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

            var controller = CreateDsesController();
            controller.ControllerContext = mock.Object;

            return controller;
        }


        [TestMethod]
        public void DetailsAction_Should_Return_View_For_Dse() {

            // Arrange
            var controller = CreateDsesController();

            // Act
            var result = controller.Details(1);

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void DetailsAction_Should_Return_NotFoundView_For_BogusDse() {

            // Arrange
            var controller = CreateDsesController();

            // Act
            var result = controller.Details(999) as ViewResult;

            // Assert
            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void EditAction_Should_Return_View_For_ValidDse() {

            // Arrange
            var controller = CreateDsesControllerAs("SomeUser");

            // Act
            var result = controller.Edit(1) as ViewResult;

            // Assert
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(DseFormViewModel));
        }

        [TestMethod]
        public void EditAction_Should_Return_View_For_InValidOwner() {

            // Arrange
            var controller = CreateDsesControllerAs("SomeOtherUser");

            // Act
            var result = controller.Edit(1) as ViewResult;

            // Assert
            Assert.AreEqual(result.ViewName, "InvalidOwner");
        }

        [TestMethod]
        public void EditAction_Should_Redirect_When_Update_Successful() {

            // Arrange
            var controller = CreateDsesControllerAs("SomeUser");
            int id = 1;

            FormCollection formValues = new FormCollection() {
                { "Title", "Another value" },
                { "Description", "Another description" }
            };

            controller.ValueProvider = formValues.ToValueProvider();
            
            // Act
            var result = controller.Edit(id, formValues) as RedirectToRouteResult;

            // Assert
            Assert.AreEqual("Details", result.RouteValues["Action"]);
            Assert.AreEqual(id, result.RouteValues["id"]);
        }

        [TestMethod]
        public void EditAction_Should_Redisplay_With_Errors_When_Update_Fails() {

            // Arrange
            var controller = CreateDsesControllerAs("SomeUser");
            int id = 1;

            FormCollection formValues = new FormCollection() {
                { "EventDate", "Bogus date value!!!"}
            };

            controller.ValueProvider = formValues.ToValueProvider();

            // Act
            var result = controller.Edit(id, formValues) as ViewResult;

            // Assert
            Assert.IsNotNull(result, "Expected redisplay of view");
            Assert.IsTrue(result.ViewData.ModelState.Sum(p => p.Value.Errors.Count) > 0, "Expected Errors");
        }

        [TestMethod]
        public void IndexAction_Should_Return_View() {

            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            var result = controller.Index(0);

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void IndexAction_Returns_TypedView_Of_List_Dse() {
            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            ViewResult result = (ViewResult)controller.Index(0);

            // Assert
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(IList<Dse>), "Index does not have an IList<Dse> as a ViewModel");
        }


        [TestMethod]
        public void IndexAction_Should_Return_PagedList() {
            
            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            //Get first page
            ViewResult result = (ViewResult)controller.Index(0);
            
            // Assert
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(PaginatedList<Dse>));
        }


        [TestMethod]
        public void IndexAction_Should_Return_PagedList_With_Total_of_100_And_Total_10_Pages() {

            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            // Get first page
            ViewResult result = (ViewResult)controller.Index(0);
            PaginatedList<Dse> list = result.ViewData.Model as PaginatedList<Dse>;

            // Assert
            Assert.AreEqual(100, list.TotalCount);
            Assert.AreEqual(10, list.TotalPages);
        }

        [TestMethod]
        public void IndexAction_Should_Return_PagedList_With_Total_of_100_And_Total_10_Pages_Given_Null()
        {

            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            // Get first page
            ViewResult result = (ViewResult)controller.Index(null);
            PaginatedList<Dse> list = result.ViewData.Model as PaginatedList<Dse>;

            // Assert
            Assert.AreEqual(100, list.TotalCount);
            Assert.AreEqual(10, list.TotalPages);
        }


        
        [TestMethod]
        public void DetailsAction_Should_Return_ViewResult() {

            // Arrange
            var controller = CreateDsesControllerAs("scottgu");

            // Act
            var result = controller.Details(1);

            // Assert
            Assert.IsNotNull(result, "There is no Details action");
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void DetailsAction_Should_Return_NotFound_For_Dse_999() {

            // Arrange
            var controller = CreateDsesControllerAs("scottgu");

            // Act
            ViewResult result = (ViewResult)controller.Details(999);

            // Assert
            Assert.AreEqual(result.ViewName, "NotFound");
        }


        [TestMethod]
        public void DetailsAction_Should_Have_ViewModel_Is_Dse() {

            // Arrange
            var controller = CreateDsesControllerAs("scottgu");

            // Act
            ViewResult result = (ViewResult)controller.Details(1);

            // Assert
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(Dse));

        }

        [TestMethod]
        public void DetailsAction_Should_Return_Dse_HostedBy_SomeUser() {

            // Arrange
            var controller = CreateDsesControllerAs("SomeUser");

            // Act

            //the mocked user is "SomeUser", who also owns the Dse
            ViewResult result = (ViewResult)controller.Details(1);
            Dse model = result.ViewData.Model as Dse;
            
            // Assert
            
            //scottgu, our mock user, is the host in the fake
            Assert.IsTrue(model.IsHostedBy("SomeUser"));
        }

        [TestMethod]
        public void CreateAction_Should_Return_ViewResult() {

            // Arrange
            var controller = CreateDsesControllerAs("scottgu");

            // Act
            var result = controller.Create();

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void CreateAction_Should_Return_DseFormViewModel() {
            
            // Arrange
            var controller = CreateDsesControllerAs("scottgu");
            
            // Act
            ViewResult result = (ViewResult)controller.Create();

            // Assert
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(DseFormViewModel));
        }

        [TestMethod]
        public void CreateAction_Should_Return_DseFormViewModel_With_New_Dse_And_Countries_List() {

            // Arrange
            var controller = CreateDsesControllerAs("scottgu");

            // Act
            ViewResult result = (ViewResult)controller.Create();
            DseFormViewModel model = (DseFormViewModel)result.ViewData.Model;
            
            // Assert
            Assert.IsNotNull(model.Dse);
            Assert.AreEqual(3, model.Countries.Count());
        }

        [TestMethod]
        public void CreateAction_Should_Return_DseFormViewModel_With_New_Dse_7_Days_In_Future() {
            
            // Arrange
            var controller = CreateDsesControllerAs("scottgu");
            
            // Act
            ViewResult result = (ViewResult)controller.Create();
            
            // Assert
            DseFormViewModel model = (DseFormViewModel)result.ViewData.Model;
            Assert.IsTrue(model.Dse.EventDate > DateTime.Today.AddDays(6) && model.Dse.EventDate < DateTime.Today.AddDays(8));
        }

        [TestMethod]
        public void CreateAction_With_New_Dse_Should_Return_View_And_Repo_Should_Contain_New_Dse()
        {
            // Arrange 
            var mock = new Mock<ControllerContext>();
            mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("ScottHa");
            mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

            var testData = FakeDseData.CreateTestDses();
            var repository = new FakeDseRepository(testData);
            var controller = new DsesController(repository);
            controller.ControllerContext = mock.Object;

            var Dse = FakeDseData.CreateDse();

            // Act
            ActionResult result = (ActionResult)controller.Create(Dse);

            // Assert
            Assert.AreEqual(102, repository.FindAllDses().Count());
            Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
        }

        [TestMethod]
        public void CreateAction_Should_Fail_Given_Bad_US_Phone_Number() {

            // Arrange
            var Dse = FakeDseData.CreateDse();
            Dse.ContactPhone = "not a good number.";
            Dse.HostedBy = "scottgu";
            var controller = CreateDsesControllerAs("scottgu");

            // Act
            ViewResult result = (ViewResult)controller.Create(Dse);

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
            Assert.IsTrue(result.ViewData.ModelState.IsValid == false);
            Assert.AreEqual(1, result.ViewData.ModelState.Sum(p => p.Value.Errors.Count), "Expected Errors");
            ModelState m = result.ViewData.ModelState["ContactPhone"];
            Assert.IsNull(m.Value);
            Assert.IsTrue(m.Errors.Count == 1);
        }


        [TestMethod]
        public void CreateAction_Should_Fail_Give_Empty_Dse() {

            // Arrange
            var controller = CreateDsesControllerAs("scottgu");
            Dse Dse = new Dse();

            // Act
            ViewResult result = (ViewResult)controller.Create(Dse);

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
            Assert.IsTrue(result.ViewData.ModelState.IsValid == false);
            Assert.AreEqual(6, result.ViewData.ModelState.Sum(p => p.Value.Errors.Count), "Expected Errors");
        }


        [TestMethod]
        public void EditAction_Should_Return_ViewResult() {
            
            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            var result = controller.Edit(1);

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void EditAction_Returns_InvalidOwner_View_When_Not_SomeUser() {
            
            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            ViewResult result = controller.Edit(1) as ViewResult;

            // Assert
            Assert.AreEqual("InvalidOwner", result.ViewName);
        }

        [TestMethod]
        public void EditAction_Uses_DseFormViewModel() {

            // Arrange
            var controller = CreateDsesControllerAs("someuser");

            // Act
            ViewResult result = controller.Edit(1) as ViewResult;

            // Assert
            Assert.IsInstanceOfType(result.ViewData.Model, typeof(DseFormViewModel));
        }

        [TestMethod]
        public void EditAction_Retrieves_Dse_1_From_Repo_And_3_Countries_And_Sets_DseViewModel() {

            // Arrange
            var controller = CreateDsesControllerAs("someuser");

            // Act
            ViewResult result = controller.Edit(1) as ViewResult;

            // Assert
            DseFormViewModel model = result.ViewData.Model as DseFormViewModel;
            Assert.AreEqual(3, model.Countries.Count());
        }

        [TestMethod]
        public void EditAction_Saves_Changes_To_Dse_1()
        {
            // Arrange
            var repo = new FakeDseRepository(FakeDseData.CreateTestDses());
            var controller = CreateDsesControllerAs("someuser");
            var form = FakeDseData.CreateDseFormCollection();
            form["Description"] = "New, Updated Description";
            controller.ValueProvider = form.ToValueProvider();

            // Act
            ActionResult result = (ActionResult)controller.Edit(1, form);
            ViewResult detailResult = (ViewResult)controller.Details(1);
            var Dse = detailResult.ViewData.Model as Dse;

            // Assert
            Assert.AreEqual(5, controller.ModelState.Count);
            Assert.AreEqual("New, Updated Description", Dse.Description);
        }

        [TestMethod]
        public void EditAction_Fails_With_Wrong_Owner() {
            
            // Arrange
            var repo = new FakeDseRepository(FakeDseData.CreateTestDses());
            var controller = CreateDsesControllerAs("fred");
            var form = FakeDseData.CreateDseFormCollection();
            controller.ValueProvider = form.ToValueProvider();

            // Act
            ViewResult result = (ViewResult)controller.Edit(1, form);

            // Assert
            Assert.AreEqual("InvalidOwner", result.ViewName);
        }

        [TestMethod]
        public void DsesController_Edit_Post_Should_Fail_Given_Bad_US_Phone_Number() {
            
            // Arrange
            var controller = CreateDsesControllerAs("someuser");
            var form = FakeDseData.CreateDseFormCollection();
            form["ContactPhone"] = "foo"; //BAD
            controller.ValueProvider = form.ToValueProvider();

            // Act
            var result = controller.Edit(1, form);

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
            var viewResult = (ViewResult)result;
            Assert.IsFalse(viewResult.ViewData.ModelState.IsValid);
            Assert.AreEqual(1, viewResult.ViewData.ModelState.Sum(p => p.Value.Errors.Count), "Expected Errors");
            ModelState m = viewResult.ViewData.ModelState["ContactPhone"];
            Assert.IsTrue(m.Errors.Count == 1);
        }



        [TestMethod]
        public void DeleteAction_Should_Return_View()
        {
            // Arrange
            var controller = CreateDsesControllerAs("someuser");

            // Act
            var result = controller.Delete(1);

            // Assert
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

        [TestMethod]
        public void DeleteAction_Should_Return_NotFound_For_999()
        {

            // Arrange
            var controller = CreateDsesControllerAs("scottgu");

            // Act
            ViewResult result = controller.Delete(999) as ViewResult;

            // Assert
            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void DeleteAction_Should_Return_InvalidOwner_For_Robcon()
        {

            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            ViewResult result = controller.Delete(1) as ViewResult;

            // Assert
            Assert.AreEqual("InvalidOwner", result.ViewName);
        }

        [TestMethod]
        public void DeleteAction_Should_Delete_Dse_1_And_Returns_Deleted_View() {

            // Arrange
            var controller = CreateDsesControllerAs("SomeUser");

            // Act
            ViewResult result = controller.Delete(1) as ViewResult;

            // Assert
            Assert.AreNotEqual("NotFound", result.ViewName);
            Assert.AreNotEqual("InvalidOwner", result.ViewName);
        }

        [TestMethod]
        public void DeleteAction_With_Confirm_Should_Delete_Dse_1_And_Returns_Deleted_View()
        {

            // Arrange
            var controller = CreateDsesControllerAs("SomeUser");

            // Act
            ViewResult result = controller.Delete(1, String.Empty) as ViewResult;

            // Assert
            Assert.AreNotEqual("NotFound", result.ViewName);
            Assert.AreNotEqual("InvalidOwner", result.ViewName);
        }

        
        [TestMethod]
        public void DeleteAction_Should_Fail_With_NotFound_Given_Invalid_Dse()
        {

            // Arrange
            var controller = CreateDsesControllerAs("robcon");

            // Act
            ViewResult result = controller.Delete(200, "") as ViewResult;

            // Assert
            Assert.AreEqual("NotFound", result.ViewName);
        }

        [TestMethod]
        public void DeleteAction_Should_Fail_With_InvalidOwner_Given_Wrong_User()
        {

            // Arrange
            var controller = CreateDsesControllerAs("scottha");

            // Act
            ViewResult result = controller.Delete(1, "") as ViewResult;

            // Assert
            Assert.AreEqual("InvalidOwner", result.ViewName);
        }
    }

    */
}
